/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.javadoc; import java.util.ArrayList; import java.util.LinkedList; import java.util.ListIterator; import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import java.text.MessageFormat; import java.net.URL; import java.lang.reflect.Field; import sun.tools.util.ModifierFilter; import sun.tools.java.ClassDeclaration; import sun.tools.java.MemberDefinition; import sun.tools.java.Constants; import sun.tools.java.ClassPath; import com.sun.javadoc.RootDoc; import org.openide.nodes.Node; import org.openide.TopManager; import org.openide.filesystems.FileObject; import org.openide.loaders.DataFolder; import org.openide.loaders.DataObject; import org.openide.windows.InputOutput; import org.openide.windows.OutputWriter; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; import org.netbeans.modules.java.JavaDataObject; import org.netbeans.modules.java.CoronaEnvironment; import org.netbeans.modules.java.CoronaClassPath; import org.netbeans.modules.java.CoronaClassFile; import org.netbeans.modules.java.ErrConsumer; import org.netbeans.modules.javadoc.settings.JavadocSettings; import org.openide.filesystems.FileObject; /** This class provides internal access to the Javadoc * * @author Petr Hrebejk */ public class JavadocInvoker extends Thread { /** The ResourceBundle */ private static final ResourceBundle bundle = NbBundle.getBundle( JavadocInvoker.class ); static final String oneoneDocletClassName = "com.sun.tools.doclets.oneone.OneOne"; // NOI18N static final String standardDocletClassName = "com.sun.tools.doclets.standard.Standard"; // NOI18N /** Stop javadoc running more than once */ static private boolean isRunning = false; /** Ouput Tab and output streams for Javadoc */ static InputOutput ioTab = null; static OutputWriter out = null; static OutputWriter err = null; /** The environment where all sources will be parsed in. */ protected CoronaEnvironment ce; /** source path and classpath determined by current contens of repository */ private CoronaClassPath srcPath = null; private CoronaClassPath binPath = null; /** Options for Javadoc run */ protected ArrayList options; /** The nodes on which will Javadoc run */ protected Node activatedNodes[]; /** List of packages and classes Javadoc generates docs for. These list contain only * unique classes and packages. Any subpackages or classe contained in packages and * subpackages are removed */ private LinkedList pckgList = new LinkedList(); private LinkedList clssList = new LinkedList(); /** List and variables needed by RootDocImpl */ private List userClasses; private List userPckgs; private ModifierFilter showAccess; /** Construtor */ public JavadocInvoker(Node[] activatedNodes) { srcPath = new CoronaClassPath(false); binPath = new CoronaClassPath(true); ce = new CoronaEnvironment ( srcPath, binPath, new myConsumer() ); options = OptionListProducer.getOptionList(); /* ArrayList adding = new ArrayList(); adding.add("-sourcepath"); adding.add(""); options.add( adding ); */ userClasses = new ArrayList(); userPckgs = new ArrayList(); showAccess = new ModifierFilter(OptionListProducer.getMembers()); this.activatedNodes = activatedNodes; setName( "JavaDocThread" ); // NOI18N } /** Tests if javadoc generation is in progress */ public static boolean isRunning() { return isRunning; } /** Parses all the files, creates envronment and RootDocImpl object and then * invokes the doclet. */ void invoke() { isRunning = true; // Parse all elements InheritanceChecksSwitch.turnOffInheritanceChecks(); ListIterator iterator = clssList.listIterator(); while( iterator.hasNext() ) parseJdo( (JavaDataObject)iterator.next() ); for ( Enumeration e1 = ce.getClasses(); e1.hasMoreElements(); ) { ClassDeclaration decl = (ClassDeclaration)e1.nextElement(); userClasses.add(decl); } iterator = pckgList.listIterator(); while( iterator.hasNext() ) parseFolder( (DataFolder)iterator.next() ); TopManager.getDefault().setStatusText( bundle.getString( "MSG_Constructing" ) ); // Create Env and feed it with fields of CoronaEnvironment EnvWrapper envWrapper = new EnvWrapper( (ClassPath)srcPath, (ClassPath)binPath, Constants.F_WARNINGS, "" ); // NOI18N envWrapper.copyCoronaEnvironment( ce ); ce = null; System.gc(); // Let the compiler stuff go RootDocImplWrapper rdiWrapper = new RootDocImplWrapper( envWrapper.getEnv(), userClasses, userPckgs, showAccess, options ); rdiWrapper.setIO( out, err ); //BhmDebug.BHM_Memory(); envWrapper = null; TopManager.getDefault().setStatusText( bundle.getString( "MSG_RunningDoclet" ) ); String docletClassName = OptionListProducer.isStyle1_1() ? oneoneDocletClassName : standardDocletClassName; //System.out.println (docletClassName); NbDocletInvoker dclInvkr = new NbDocletInvoker( docletClassName, null, err ); dclInvkr.validOptions( rdiWrapper.options( options ) ); dclInvkr.start( rdiWrapper ); dclInvkr = null; // allows to free the memory after running javadoc setStaticField( "com.sun.tools.doclets.Configuration", "root", null); // NOI18N setStaticField( "com.sun.tools.doclets.HtmlDocWriter", "configuration", null); // NOI18N setStaticField( "com.sun.tools.doclets.standard.HtmlStandardWriter", "configuration", null); // NOI18N setStaticField( "com.sun.tools.doclets.standard.HtmlStandardWriter", "currentcd", null); // NOI18N setStaticField( "com.sun.tools.javadoc.MethodDocImpl", "map", null); // NOI18N setStaticField( "com.sun.tools.javadoc.FieldDocImpl", "map", null); // NOI18N setStaticField( "com.sun.tools.javadoc.ConstructorDocImpl", "map", null); // NOI18N setStaticField( "com.sun.tools.javadoc.ClassDocImpl", "classMap", null); // NOI18N setStaticField( "com.sun.tools.javadoc.PackageDocImpl", "packageMap", null); // NOI18N // Resets group setting after running javadoc rdiWrapper = null; System.gc(); // All the stuff becomes trash - hopefully TopManager.getDefault().setStatusText( "" ); // NOI18N InheritanceChecksSwitch.turnOnInheritanceChecks(); isRunning = false; String destDir = OptionListProducer.getDestinationDirectory(); String mssg = MessageFormat.format( bundle.getString( "FMT_GeneratingFinished" ), new Object[] { destDir } ); NotifyDescriptor nd = new NotifyDescriptor.Confirmation ( mssg, NotifyDescriptor.YES_NO_OPTION ); TopManager.getDefault().notify( nd ); if ( nd.getValue().equals ( NotifyDescriptor.YES_OPTION ) ) { //System.out.println ( nd.getValue() ); try { URL url = null; if ( OptionListProducer.isStyle1_1() ) url = new URL( "file:///" + destDir + java.io.File.separator + "packages.html" ); // NOI18N else url = new URL( "file:///" + destDir + java.io.File.separator + "index.html" ); // NOI18N TopManager.getDefault().showUrl( url ); } catch ( java.net.MalformedURLException e ) { throw new InternalError( "Can't find documentation index fier" ); // NOI18N } } } /** Parses one JavaDatObject */ private void parseJdo( JavaDataObject jdo ) { try { CoronaClassFile ccf = new CoronaClassFile( jdo.getPrimaryFile( ) ); TopManager.getDefault().setStatusText( bundle.getString( "MSG_Parsing" ) + " " + ccf.getName()); ce.x_parseFile ( ccf ); } catch (java.io.FileNotFoundException e) { TopManager.getDefault().notifyException( e ); } } /** Parses all java files in folder and it's subfolders */ private void parseFolder(DataFolder folder) { boolean isPackage = false; DataObject dobj[] = folder.getChildren(); for( int i = 0; i < dobj.length; i++ ) if ( dobj[i] instanceof JavaDataObject ) { try { CoronaClassFile ccf = new CoronaClassFile( dobj[i].getPrimaryFile( ) ); TopManager.getDefault().setStatusText( bundle.getString( "MSG_Parsing" ) + " " + ccf.getName()); ce.parseFile ( ccf ); if (!isPackage) { isPackage = true; userPckgs.add( folder.getPrimaryFile().getPackageName('.') ); } } catch (java.io.FileNotFoundException e) { TopManager.getDefault().notifyException( e ); } } else if (dobj[i] instanceof DataFolder) { parseFolder( (DataFolder)dobj[i] ); } } /** Inner class consuming parser's errors */ class myConsumer implements ErrConsumer { public void pushError (FileObject errorFile, int line, int column, String message, String referenceText) { err.println ( bundle.getString( "MSG_Error" ) + " " + line + ":" + column + " " + message ); } } /** Adds package to list only if is not subpackage of any othetr and remove any * present subpackages of this package */ private void addPackage( DataFolder df ) { ListIterator iterator = pckgList.listIterator(); DataFolder cdf; while (iterator.hasNext()) { cdf = (DataFolder)iterator.next(); if ( df.getPrimaryFile().getPackageName('.').startsWith( cdf.getPrimaryFile().getPackageName('.'))) return; else if ( cdf.getPrimaryFile().getPackageName('.').startsWith( df.getPrimaryFile().getPackageName('.'))) iterator.remove(); } pckgList.add( df ); } /** Tests if the class is in any package */ private boolean classInPackage( JavaDataObject jdo ) { ListIterator iterator = pckgList.listIterator(0); while (iterator.hasNext()) if ( jdo.getPrimaryFile().getPackageName('.').startsWith( ((DataObject)iterator.next()).getPrimaryFile().getPackageName('.'))) return true; return false; } /** Makes lists of packages and classes and removes not uniques entries */ private void createLists() { DataFolder df; JavaDataObject jdo; TopManager.getDefault().setStatusText( bundle.getString( "MSG_GeneratingList" ) ); for( int i = 0; i < activatedNodes.length; ++i ) if ((df = (DataFolder)activatedNodes[i].getCookie( DataFolder.class )) != null ) { addPackage( df ); } else if ((jdo = (JavaDataObject)activatedNodes[i].getCookie( JavaDataObject.class )) != null ) { clssList.add( jdo ); } // Remove all classes contained in packages ListIterator iterator = clssList.listIterator(); while (iterator.hasNext()) if ( classInPackage( (JavaDataObject)iterator.next())) iterator.remove(); } /** The run method creates lists of packages and classes to be processed and * class invoke(). */ public void run() { createLists(); invoke(); } /** Gets the Input/Output tab */ static InputOutput getIO() { // if ( ioTab != null ) { //System.out.println("IOC " + ioTab.isClosed() ); // NOI18N // ioTab.closeInputOutput(); // } if ( ioTab == null ) { ioTab = TopManager.getDefault().getIO( bundle.getString( "CTL_Javadoc_IOTab" ) ); ioTab.setErrSeparated (true); ioTab.setOutputVisible (true); ioTab.setErrVisible (true); out = ioTab.getOut (); ioTab.setFocusTaken (true); err = ioTab.getErr (); ioTab.select (); } else { try { out.reset(); err.reset(); ioTab.select(); } catch (java.io.IOException e) { TopManager.getDefault().notifyException( e ); } } return ioTab; } /** Sets field in class on value */ private static void setStaticField( String className, String fieldName, Object value) { try { Class clazz = Class.forName( className ); Field field = clazz.getDeclaredField( fieldName ); field.setAccessible( true ); field.set( clazz, value ); } catch (ClassNotFoundException e) { } catch (IllegalAccessException e) { } catch (NoSuchFieldException e) { } } } /* * Log * 17 Gandalf 1.16 2/11/00 Petr Hrebejk Memory leak in javadoc * generation fixed * 16 Gandalf 1.15 1/13/00 Petr Hrebejk i18n mk3 * 15 Gandalf 1.14 1/12/00 Petr Hrebejk i18n * 14 Gandalf 1.13 1/11/00 Petr Hrebejk Better handling of ioTab * 13 Gandalf 1.12 1/10/00 Petr Hrebejk Bug 4747 - closing of * output tab fixed * 12 Gandalf 1.11 1/3/00 Petr Hrebejk Bugfix 4747 * 11 Gandalf 1.10 11/25/99 Petr Hrebejk Parser change in Java * loader module reflected * 10 Gandalf 1.9 11/10/99 Petr Hrebejk Displaying packages.html * instad of index.html for 1.1 style documentation * 9 Gandalf 1.8 11/9/99 Petr Hrebejk Javadoc runs in * ExecEngine and captures all output * 8 Gandalf 1.7 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 7 Gandalf 1.6 9/15/99 Petr Hrebejk New status texts + * localization * 6 Gandalf 1.5 6/11/99 Petr Hrebejk * 5 Gandalf 1.4 6/9/99 Ian Formanek Fixed to compile * 4 Gandalf 1.3 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 3 Gandalf 1.2 5/14/99 Petr Hrebejk * 2 Gandalf 1.1 4/23/99 Ian Formanek better capitalization of * output window tab * 1 Gandalf 1.0 4/23/99 Petr Hrebejk * $ */